package com.smartfast4j.manager.common.interceptor;

import com.alibaba.fastjson.JSON;
import com.smartfast4j.common.annotation.PermissionLimit;
import com.smartfast4j.common.bean.R;
import com.smartfast4j.common.component.cache.CacheService;
import com.smartfast4j.common.util.WebUtil;
import com.smartfast4j.manager.common.bean.LoginUserInfo;
import com.smartfast4j.manager.modules.sys.service.SysUserService;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.handler.HandlerInterceptorAdapter;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.Arrays;
import java.util.Set;

/**
 * 权限拦截器
 */
@Component
public class PermissionInterceptor extends HandlerInterceptorAdapter {

    private static final Logger logger = LoggerFactory.getLogger(PermissionInterceptor.class);

    @Autowired
    private SysUserService sysUserService;

    @Autowired
    private CacheService cacheService;

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        logger.debug(">>>PermissionInterceptor>>>>>>>在请求处理之前进行调用（Controller方法调用之前）");
        if (!(handler instanceof HandlerMethod)) {
            return super.preHandle(request, response, handler);
        }
        try{
            HandlerMethod method = (HandlerMethod) handler;
            //获取方法上的PermessionLimit注解
            PermissionLimit permission = method.getMethodAnnotation(PermissionLimit.class);
            if (permission != null) {
                //访问这个资源需要的权限
                String[] permissionValue = permission.value();//获取注解上的value
                //获取登录用户信息
                LoginUserInfo loginUser = sysUserService.getCurrLoginUser();
                //该登录用户所拥有的权限
                Set<String> perms  = loginUser.getPerms();
                if(!perms.containsAll(Arrays.asList(permissionValue))){
                    //1.判断是否为ajax请求
                    //String ajaxRequest = request.getHeader("ajaxRequest");//自定义AJAX请求头，用于标识是否为ajax请求
                    if(WebUtil.isAjax(request)){
                        logger.debug("----PermissionInterceptor本次拦截的{}请求为AJAX请求-----",request.getRequestURI());
                        response.setHeader("permissionLimit", "permissionLimit");//在响应头设置权限错误状态
                    }else {
                        //用户所拥有的权限列表不包含访问目标资源需要的权限，无法访问
                        WebUtil.writeJsonRes(JSON.toJSONString(R.fail("没有访问权限，请联系管理员授权")),response);
                    }
                    /*if (StringUtils.isNotEmpty(ajaxRequest) && Boolean.valueOf(ajaxRequest)) {
                        logger.debug("----PermissionInterceptor本次请求为AJAX请求-----");
                        response.setHeader("permissionLimit", "permissionLimit");//在响应头设置权限错误状态
                    }else {
                        //用户所拥有的权限列表不包含访问目标资源需要的权限，无法访问
                        WebUtil.writeJsonRes(JSON.toJSONString(R.fail("没有访问权限，请联系管理员授权")),response);
                    }*/
                    return false;//返回false取消当前请求，不再往下执行
                }
            }else {
                //获取登录用户信息
                LoginUserInfo loginUser = sysUserService.getCurrLoginUser();
                if(loginUser != null){
                    //该登录用户所拥有的权限
                    Set<String> perms = loginUser.getPerms();
                    //获取要访问的资源
                    String requestUri = request.getRequestURI();
                    //从缓存中获取资源访问权限
                    String perm = cacheService.get(requestUri);//获取访问该资源需要使用的权限
                    if (StringUtils.isNotEmpty(perm)) {
                        if (!perms.containsAll(Arrays.asList(perm.trim().split(",")))) {
                            if(WebUtil.isAjax(request)){
                                logger.debug("----PermissionInterceptor本次拦截的{}请求为AJAX请求-----",requestUri);
                                response.setHeader("permissionLimit", "permissionLimit");//在响应头设置权限错误状态
                            }else {
                                //用户所拥有的权限列表不包含访问目标资源需要的权限，无法访问
                                WebUtil.writeJsonRes(JSON.toJSONString(R.fail("没有访问权限，请联系管理员授权")),response);
                            }
                            //1.判断是否为ajax请求
                           /* String ajaxRequest = request.getHeader("ajaxRequest");//自定义AJAX请求头，用于标识是否为ajax请求
                            if (StringUtils.isNotEmpty(ajaxRequest) && Boolean.valueOf(ajaxRequest)) {
                                logger.debug("----PermissionInterceptor本次请求为AJAX请求-----");
                                response.setHeader("permissionLimit", "permissionLimit");//在响应头设置权限错误状态
                            }else {
                                //用户所拥有的权限列表不包含访问目标资源需要的权限，无法访问
                                WebUtil.writeJsonRes(JSON.toJSONString(R.fail("没有访问权限，请联系管理员授权")),response);
                            }*/
                            return false;//返回false取消当前请求，不再往下执行
                        }
                    }
                }
            }
        }catch (Exception e){
            logger.error(e.getMessage(),e);
        }
        return super.preHandle(request, response, handler);// 只有返回true才会继续向下执行，返回false取消当前请求
    }

    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
        logger.debug(">>>PermissionInterceptor>>>>>>>请求处理之后进行调用，但是在视图被渲染之前（Controller方法调用之后）");
        super.postHandle(request, response, handler, modelAndView);
    }

    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex)
            throws Exception {
        logger.debug(">>>PermissionInterceptor>>>>>>>在整个请求结束之后被调用，也就是在DispatcherServlet 渲染了对应的视图之后执行（主要是用于进行资源清理工作）");
    }
}
